package org.example.config;

import org.example.annotation.MybatisQueryScan;
import org.example.core.plugin.QueryInterceptor;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

public class QueryEntityImportRegistryBeanDefinition implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry, importBeanNameGenerator);
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//        ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry);
        Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(MybatisQueryScan.class.getName());
        if(CollectionUtils.isEmpty(annotationAttributes)){
            return;
        }

        Object basePackage = annotationAttributes.get("basePackage");
        String packageStr = Objects.nonNull(basePackage) ? basePackage.toString() : "";

        QueryEntityScanBeanDefinition scan = new QueryEntityScanBeanDefinition(registry);

        Set<BeanDefinitionHolder> beanDefinitionHolders = scan.doScan(packageStr);

        List<? extends Class<?>> classes = beanDefinitionHolders.stream().map(beanDefinitionHolder -> {
            try {
                return Class.forName(beanDefinitionHolder.getBeanDefinition().getBeanClassName());
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(QueryInterceptor.class.getName()).getBeanDefinition();
        beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(classes);
        registry.registerBeanDefinition(Objects.requireNonNull(beanDefinition.getBeanClassName()),beanDefinition);

    }
}
